package com.zhiyin.seal.controller;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhiyin.seal.anno.OperateLog;
import com.zhiyin.seal.entity.bo.*;
import com.zhiyin.seal.entity.dto.*;
import com.zhiyin.seal.entity.vo.*;
import com.zhiyin.seal.service.*;
import com.zhiyin.seal.util.BeanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 公司业务控制器
 */
@RestController
@RequestMapping("/company")
public class CompanyController {

    @Autowired
    CompanyService companyService;

    @Autowired
    UserService userService;

    @Autowired
    SealService sealService;

    @Autowired
    ApprovalService approvalService;

    @Autowired
    ApplyService applyService;

    @PostMapping("/create")
    public ResponseDTO<Boolean> addCompany(@RequestBody CompanyDTO companyDTO){
        CompanyBo companyBo = BeanUtil.copy(companyDTO,CompanyBo.class);
        if(companyBo.getAuthStatus() == null){
            companyBo.setAuthStatus(0);
        }
        // 添加公司
        Boolean result = companyService.addCompany(companyBo);
        if(result){
            companyBo = companyService.getLastCompanyByCreateUser(companyDTO.getCreateUser());
            // 初始化部门
            result = companyService.initDepartment(companyBo);
            if(result){
                // 绑定用户与公司关系
                companyService.addCompanyUser(companyBo.getCreateUser(),companyBo.getId());
                CompanyUserBo companyUserBo = companyService.getLastCompanyUser(companyBo.getCreateUser(),companyBo.getId());
                // 设置默认公司
                companyService.setDefaultCompany(companyUserBo);

                return ResponseDTO.succData(true);
            }
        }

        return ResponseDTO.succData(false);
    }

    @GetMapping("/list/all")
    public ResponseDTO<List<CompanyVo>> getAllCompanyList(@RequestParam String keywords){
        List<CompanyVo> companyVoList = BeanUtil.copyList(companyService.getAllCompanyList(keywords),CompanyVo.class);
        Map<Long,UserBo> userBoMap = Maps.newHashMap();
        List<Long> userIdList = Lists.newArrayList();
        userIdList.add(0l);
        for(CompanyVo companyVo:companyVoList){
            userIdList.add(companyVo.getBelongUser());
        }
        List<UserBo> userBoList = userService.getUserListByIds(userIdList);
        for(UserBo userBo:userBoList){
            userBoMap.put(userBo.getId(),userBo);
        }
        for(CompanyVo companyVo:companyVoList){
            UserBo userBo = userBoMap.get(companyVo.getBelongUser());
            companyVo.setUserName(userBo.getNickName());
            companyVo.setPhoneNumber(userBo.getPhoneNumber());
        }

        return ResponseDTO.succData(companyVoList);
    }

    @GetMapping("/mylist")
    public ResponseDTO<List<MyCompanyVo>> getMyCompanyList(@RequestParam Long userId){
        // 查询用户关联的公司
        List<CompanyUserBo> companyUserBoList = companyService.getMyCompanyList(userId);
        Map<Long,Boolean> companyUserMap = Maps.newHashMap();
        companyUserMap = companyUserBoList.stream().collect(Collectors.toMap(CompanyUserBo::getCompanyId,CompanyUserBo::getDefaultCompany));
        // 查询公司
        List<Long> companyIds = Lists.newArrayList();
        companyService.buildCompanyIdListByCompanyUserList(companyUserBoList,companyIds);
        List<CompanyBo> companyBoList = companyService.getCompanyListByIds(companyIds);
        List<MyCompanyVo> myCompanyVoList = BeanUtil.copyList(companyBoList,MyCompanyVo.class);
        if(myCompanyVoList != null){
            for (MyCompanyVo myCompanyVo : myCompanyVoList) {
                // 赋值用户名称
                UserBo userBo = userService.getUserInfoByIdAndCompany(myCompanyVo.getBelongUser(),myCompanyVo.getId());
                if(userBo != null){
                    myCompanyVo.setBelongUserName(userBo.getNickName());
                }
                // 赋值是否为默认公司
                Boolean def = companyUserMap.get(myCompanyVo.getId());
                myCompanyVo.setDefaultCompany(def);
            }
        }

        return ResponseDTO.succData(myCompanyVoList);
    }

    @GetMapping("/switch")
    public ResponseDTO<Boolean> switchCompany(@RequestParam Long userId,@RequestParam Long companyId){
        return ResponseDTO.succData(companyService.switchCompany(userId,companyId));
    }

    @GetMapping("/default")
    public ResponseDTO<CompanyVo> getUserDefaultCompany(@RequestParam Long userId){
        CompanyBo companyBo = companyService.getUserDefaultCompany(userId);
        if(companyBo != null){
            CompanyVo companyVo = BeanUtil.copy(companyBo,CompanyVo.class);
            // 查询公司管理员
            List<CompanyAdminBo> companyAdminBoList = companyService.getCompanyAdminList(companyBo.getId());
            if(companyAdminBoList != null){
                List<UserBo> userBoList = Lists.newArrayList();
                companyService.buildUserInfoListByCompanyAdminList(companyAdminBoList,userBoList);
                companyVo.setAdminList(BeanUtil.copyList(userBoList,UserVo.class));
            }
            // 查询所属人
            UserBo userBo = companyService.getCompanyBelongUser(companyBo.getId());
            UserVo userVo = BeanUtil.copy(userBo,UserVo.class);
            companyVo.setUserInfo(userVo);

            // 查询印章列表
            List<AdminSealBo> adminSealBoList = userService.getAdminSealList(userId,companyBo.getId());
            companyVo.setAdminSealList(BeanUtil.copyList(adminSealBoList,AdminSealVo.class));
            // 查询功能列表
            List<AdminFunctionBo> adminFunctionBoList = userService.getAdminFunctionList(userId,companyBo.getId());
            companyVo.setAdminFunctionList(BeanUtil.copyList(adminFunctionBoList,AdminFunctionVo.class));

            return ResponseDTO.succData(companyVo);
        }

        return ResponseDTO.succData(null);
    }

    @GetMapping("/info")
    public ResponseDTO<CompanyVo> getCompanyInfo(@RequestParam Long companyId){
        return ResponseDTO.succData(BeanUtil.copy(companyService.getCompanyById(companyId),CompanyVo.class));
    }

    @GetMapping("/info/user")
    public ResponseDTO<CompanyVo> getCompanyUserInfo(@RequestParam Long companyId,@RequestParam Long userId){
        CompanyBo companyBo = companyService.getCompanyById(companyId);
        if(companyBo != null){
            CompanyVo companyVo = BeanUtil.copy(companyBo,CompanyVo.class);
            // 查询公司管理员
            List<CompanyAdminBo> companyAdminBoList = companyService.getCompanyAdminList(companyBo.getId());
            if(companyAdminBoList != null){
                List<Long> userIds = Lists.newArrayList();
                companyService.buildUserIdListByCompanyAdminList(companyAdminBoList,userIds);
                List<UserBo> userBoList = userService.getUserListByUserIdsAndCompany(userIds,companyId);
                companyVo.setAdminList(BeanUtil.copyList(userBoList,UserVo.class));
            }
            // 查询所属人
            companyVo.setUserInfo(BeanUtil.copy(companyService.getCompanyBelongUser(companyId),UserVo.class));

            // 查询印章列表
            List<AdminSealBo> adminSealBoList = userService.getAdminSealList(userId,companyBo.getId());
            companyVo.setAdminSealList(BeanUtil.copyList(adminSealBoList,AdminSealVo.class));
            // 查询功能列表
            List<AdminFunctionBo> adminFunctionBoList = userService.getAdminFunctionList(userId,companyBo.getId());
            companyVo.setAdminFunctionList(BeanUtil.copyList(adminFunctionBoList,AdminFunctionVo.class));

            return ResponseDTO.succData(companyVo);
        }

        return ResponseDTO.succData(null);
    }

    @GetMapping("/detail")
    public ResponseDTO<CompanyDetailVo> getCompanyDetail(@RequestParam Long companyId){
        CompanyBo companyBo = companyService.getCompanyById(companyId);
        if(companyBo == null){
            return null;
        }
        UserBo userBo = userService.getUserInfoByIdAndCompany(companyBo.getBelongUser(),companyBo.getId());
        CompanyDetailVo companyDetailVo = BeanUtil.copy(companyBo,CompanyDetailVo.class);
        UserVo userVo = BeanUtil.copy(userBo,UserVo.class);
        companyDetailVo.setBelongUser(userVo);
        // 查询公司管理员
        List<CompanyAdminBo> companyAdminBoList = companyService.getCompanyAdminList(companyId);
        if(companyAdminBoList != null){
            List<UserVo> userVoList = Lists.newArrayList();
            for (CompanyAdminBo companyAdminBo : companyAdminBoList) {
                userBo = userService.getUserInfoByIdAndCompany(companyAdminBo.getUserId(),companyAdminBo.getCompanyId());
                if(userBo != null){
                    userVoList.add(BeanUtil.copy(userBo,UserVo.class));
                }
            }
            companyDetailVo.setAdminList(userVoList);
        }
        return ResponseDTO.succData(companyDetailVo);
    }

    @GetMapping("/detail/name")
    public ResponseDTO<CompanyDetailVo> getCompanyDetailByName(@RequestParam String companyName){
        CompanyBo companyBo = companyService.getCompanyByNameSingle(companyName);
        if(companyBo == null){
            return ResponseDTO.succData(null);
        }
        UserBo userBo = userService.getUserInfoById(companyBo.getBelongUser());
        CompanyDetailVo companyDetailVo = BeanUtil.copy(companyBo,CompanyDetailVo.class);
        UserVo userVo = BeanUtil.copy(userBo,UserVo.class);
        companyDetailVo.setBelongUser(userVo);

        return ResponseDTO.succData(companyDetailVo);
    }

    @GetMapping("/resource")
    public ResponseDTO<CompanyResourceVo> getCompanyResource(@RequestParam Long companyId){
        List<CompanyDepartmentBo> companyDepartmentBoList = companyService.getDepartmentListByCompanyId(companyId);
        List<CompanyUserBo> companyUserBoList = companyService.getUserListByCompanyId(companyId);
        List<UserBo> userBoList = Lists.newArrayList();
        companyService.buildUserInfoListByCompanyUserList(companyUserBoList,userBoList);

        CompanyResourceVo companyResourceVo = new CompanyResourceVo();
        companyResourceVo.setDepartmentVoList(BeanUtil.copyList(companyDepartmentBoList, CompanyDepartmentVo.class));
        companyResourceVo.setUserVoList(BeanUtil.copyList(userBoList,UserVo.class));
        return ResponseDTO.succData(companyResourceVo);
    }

    @GetMapping("/department/resource")
    public ResponseDTO<CompanyResourceVo> getDepartmentResource(@RequestParam Long departmentId){
        List<CompanyDepartmentBo> companyDepartmentBoList = companyService.getDepartmentListByDepartmentId(departmentId);
        List<CompanyUserBo> companyUserBoList = companyService.getUserListByDepartmentId(departmentId);
        List<UserBo> userBoList = Lists.newArrayList();
        companyService.buildUserInfoListByCompanyUserList(companyUserBoList,userBoList);

        CompanyResourceVo companyResourceVo = new CompanyResourceVo();
        companyResourceVo.setDepartmentVoList(BeanUtil.copyList(companyDepartmentBoList, CompanyDepartmentVo.class));
        companyResourceVo.setUserVoList(BeanUtil.copyList(userBoList,UserVo.class));
        return ResponseDTO.succData(companyResourceVo);
    }

    @PostMapping("/department/add")
    public ResponseDTO<Boolean> addDepartment(@RequestBody CompanyDepartmentDTO companyDepartmentDTO){
        return ResponseDTO.succData(companyService.addDepartment(BeanUtil.copy(companyDepartmentDTO,CompanyDepartmentBo.class)));
    }

    @GetMapping("/department/update")
    public ResponseDTO<Boolean> modifyDepartmentName(@RequestParam(required = true) String name,@RequestParam Long id){
        return ResponseDTO.succData(companyService.updateDepartmentName(name,id));
    }

    @GetMapping("/department/remove")
    public ResponseDTO<Boolean> removeDepartment(@RequestParam Long id){
        return ResponseDTO.succData(companyService.removeDepartment(id));
    }

    @GetMapping("/alluserlist")
    public ResponseDTO<List<UserVo>> getAllUserList(@RequestParam Long companyId){
        List<CompanyUserBo> companyUserBoList = companyService.getAllUserList(companyId);
        List<UserBo> userBoList = Lists.newArrayList();
        companyService.buildUserInfoListByCompanyUserList(companyUserBoList,userBoList);

        return ResponseDTO.succData(BeanUtil.copyList(userBoList,UserVo.class));
    }

    @PostMapping("/add/admin")
    public ResponseDTO<Boolean> addCompanyAdmin(@RequestBody AddCompanyAdminDTO adminDTO){
        return ResponseDTO.succData(companyService.addCompanyAdmin(BeanUtil.copy(adminDTO,CompanyAdminBo.class)));
    }

    @GetMapping("/admin/remove")
    public ResponseDTO<Boolean> removeAdmin(@RequestParam Long companyId,@RequestParam Long userId){
        // 解除管理员功能权限
        companyService.deleteAdminFunction(userId,companyId);
        // 解除管理员印章关系
        companyService.deleteAdminSeal(userId,companyId);
        // 解除管理员公司关系
        companyService.deleteCompanyAdmin(userId,companyId);

        return ResponseDTO.succData(true);
    }

    @PostMapping("/user/add")
    public ResponseDTO<Boolean> addUser(@RequestBody CompanyUserDTO companyUserDTO){
        return ResponseDTO.succData(companyService.addCompanyUser(BeanUtil.copy(companyUserDTO,CompanyUserBo.class)));
    }

    @PostMapping("/user/moveup")
    public ResponseDTO<Boolean> moveUserUp(@RequestBody MoveUserDTO moveUserDTO){
        return ResponseDTO.succData(companyService.moveUserUp(moveUserDTO.getUserId(),moveUserDTO.getDepartmentId(),moveUserDTO.getCompanyId()));
    }

    @PostMapping("/user/movedown")
    public ResponseDTO<Boolean> moveUserDown(@RequestBody MoveUserDTO moveUserDTO){
        return ResponseDTO.succData(companyService.moveUserDown(moveUserDTO.getUserId(),moveUserDTO.getDepartmentId(),moveUserDTO.getCompanyId()));
    }

    @GetMapping("/update/user/alias")
    public ResponseDTO<Boolean> updateUserAlias(@RequestParam Long userId,@RequestParam Long companyId,@RequestParam String userAlias){
        return ResponseDTO.succData(companyService.updateUserAlias(userId,companyId,userAlias));
    }

    @GetMapping("/user/remove")
    public ResponseDTO<Boolean> removeUser(@RequestParam Long userId,@RequestParam Long companyId){
        // 解除管理员功能权限
        companyService.deleteAdminFunction(userId,companyId);
        // 解除管理员印章关系
        companyService.deleteAdminSeal(userId,companyId);
        // 解除管理员公司关系
        companyService.deleteCompanyAdmin(userId,companyId);
        // 解除审批关系
        approvalService.removeApprovalUser(userId,companyId);
        // 解除抄送关系
        approvalService.removeApprovalCC(userId,companyId);
        // 解除用户与公司关系
        companyService.removeUser(userId,companyId);

        return ResponseDTO.succData(true);
    }

    @GetMapping("/alarmrecordlist")
    public ResponseDTO<List<AlarmRecordVo>> getAlarmRecordList(@RequestParam Long companyId){
        List<AlarmRecordBo> alarmRecordBoList = companyService.getAlarmRecordList(companyId);
        List<AlarmRecordVo> alarmRecordVoList = BeanUtil.copyList(alarmRecordBoList,AlarmRecordVo.class);

        List<Long> sealIds = Lists.newArrayList();
        sealService.buildSealIdsByAlarmRecordList(alarmRecordBoList,sealIds);
        List<SealBo> sealBoList = sealService.getSealListByIdsAndCompany(sealIds,companyId);
        Map<Long,SealBo> sealBoMap = Maps.newHashMap();
        if(sealBoList != null){
            sealBoMap = sealBoList.stream().collect(Collectors.toMap(SealBo::getId,seal->seal));
        }

        List<Long> userIds = Lists.newArrayList();
        companyService.buildUserIdsByAlarmRecordList(alarmRecordBoList,userIds);
        List<UserBo> userBoList = userService.getUserListByUserIdsAndCompany(userIds,companyId);
        Map<Long,UserBo> userBoMap = Maps.newHashMap();
        if(userBoList != null){
            userBoMap = userBoList.stream().collect(Collectors.toMap(UserBo::getId,user->user));
        }
        // 填充印章和人员属性
        if(alarmRecordVoList != null){
            for (AlarmRecordVo alarmRecordVo : alarmRecordVoList) {
                Long sealId = alarmRecordVo.getSealId();
                Long userId = alarmRecordVo.getCreateUser();
                if(sealId != null){
                    alarmRecordVo.setSealVo(BeanUtil.copy(sealBoMap.get(sealId),SealVo.class));
                }
                if(userId != null){
                    alarmRecordVo.setUserVo(BeanUtil.copy(userBoMap.get(userId),UserVo.class));
                }
            }
        }

        return ResponseDTO.succData(alarmRecordVoList);
    }

    @GetMapping("/contracttypelist")
    public ResponseDTO<List<CompanyContractTypeVo>> getCompanyContractTypeList(@RequestParam Long companyId){
        return ResponseDTO.succData(BeanUtil.copyList(companyService.getCompanyContractTypeList(companyId),CompanyContractTypeVo.class));
    }

    @GetMapping("/subcontracttypelist")
    public ResponseDTO<List<CompanyContractTypeVo>> getContractTypeListByParentId(@RequestParam Long id,@RequestParam Long companyId){
        return ResponseDTO.succData(BeanUtil.copyList(companyService.getCompanyContractTypeListByParentId(id,companyId),CompanyContractTypeVo.class));
    }

    @PostMapping("/addcontracttype")
    public ResponseDTO<Boolean> addCompanyContractType(@RequestBody CompanyContractTypeDTO contractTypeDTO){
        return ResponseDTO.succData(companyService.addCompanyContractType(BeanUtil.copy(contractTypeDTO,CompanyContractTypeBo.class)));
    }

    @GetMapping("/deletecontracttype")
    public ResponseDTO<Boolean> deleteCompanyContractType(@RequestParam Long id){
        return ResponseDTO.succData(companyService.deleteCompanyContractType(id));
    }

    @GetMapping("/join")
    public ResponseDTO<Boolean> joinCompany(@RequestParam Long companyId,@RequestParam Long userId){
        companyService.joinCompany(companyId,userId);
        return ResponseDTO.succData(true);
    }

    @GetMapping("/join2")
    public ResponseDTO<Boolean> joinCompany2(@RequestParam Long companyId,@RequestParam Long userId,@RequestParam String nickName){
        companyService.joinCompany2(companyId,userId,nickName);
        return ResponseDTO.succData(true);
    }

    @GetMapping("/transfer")
    public ResponseDTO<Boolean> transferCompany(@RequestParam Long companyId,@RequestParam Long userId){
        return ResponseDTO.succData(companyService.transferCompany(companyId,userId));
    }

    @GetMapping("/admin/seal/list")
    public ResponseDTO<List<AdminSealVo>> getAdminSealList(@RequestParam Long companyId,@RequestParam Long userId){
        List<AdminSealBo> adminSealBoList = userService.getAdminSealList(userId,companyId);
        return ResponseDTO.succData(BeanUtil.copyList(adminSealBoList,AdminSealVo.class));
    }

    @PostMapping("/admin/seal/update")
    public ResponseDTO<Boolean> updateAdminSeal(@RequestBody AdminSealDTO adminSealDTO){
        AdminSealBo adminSealBo = BeanUtil.copy(adminSealDTO,AdminSealBo.class);
        return ResponseDTO.succData(userService.updateAdminSeal(adminSealBo));
    }

    @GetMapping("/admin/function/list")
    public ResponseDTO<List<AdminFunctionVo>> getAdminFunctionList(@RequestParam Long companyId,@RequestParam Long userId){
        List<AdminFunctionBo> adminFunctionBoList = userService.getAdminFunctionList(userId,companyId);
        return ResponseDTO.succData(BeanUtil.copyList(adminFunctionBoList,AdminFunctionVo.class));
    }

    @PostMapping("/admin/function/update")
    public ResponseDTO<Boolean> updateAdminFunction(@RequestBody AdminFunctionDTO adminFunctionDTO){
        AdminFunctionBo adminFunctionBo = BeanUtil.copy(adminFunctionDTO,AdminFunctionBo.class);
        return ResponseDTO.succData(userService.updateAdminFunction(adminFunctionBo));
    }

    @GetMapping("/quit")
    public ResponseDTO<Boolean> quitCompany(@RequestParam Long companyId,@RequestParam Long userId){
        // 解除审批关系
        approvalService.removeApprovalUser(userId,companyId);
        // 解除抄送关系
        approvalService.removeApprovalCC(userId,companyId);
        // 解除管理员关系
        companyService.deleteCompanyAdmin(userId,companyId);
        // 解除管理员功能权限
        companyService.deleteAdminFunction(userId,companyId);
        // 解除管理员印章关系
        companyService.deleteAdminSeal(userId,companyId);
        // 解除用户与公司关系
        companyService.removeUser(userId,companyId);

        return ResponseDTO.succData(true);
    }

    @GetMapping("/remove")
    public ResponseDTO<Boolean> removeCompany(@RequestParam Long companyId){
        // 解除公司与用户的所有关系
        companyService.removeCompanyUser(companyId);
        // 解除公司与印章的所有关系
        sealService.removeCompanyAllSeal(companyId);
        // 解除公司所有理员关系
        companyService.removeCompanyAllAdmin(companyId);
        // 解除管理员功能权限
        companyService.deleteAllAdminFunction(companyId);
        // 解除管理员印章关系
        companyService.deleteAllAdminSeal(companyId);
        // 解除审批流
        approvalService.removeCompanyApprovalProcess(companyId);
        // 删除并且备份公司信息
        companyService.removeCompany(companyId);

        return ResponseDTO.succData(true);
    }

    @GetMapping("/has/auth")
    public ResponseDTO<CompanyAuthVo> getAuthCompany(@RequestParam String name){
//        CompanyAuthBo companyAuthBo =  companyService.getAuthCompany(name);
//        if(companyAuthBo != null){
//
//            return ResponseDTO.succData(BeanUtil.copy(companyAuthBo,CompanyAuthVo.class));
//        }

        return ResponseDTO.succData(null);
    }

    @GetMapping("/auth")
    public ResponseDTO<CompanyAuthVo> authCompany(@RequestParam String name){
        // 检查是否已经认证
        CompanyAuthBo companyAuthBo =  companyService.getAuthCompany(name);
        if(companyAuthBo != null){
            return ResponseDTO.succData(BeanUtil.copy(companyAuthBo,CompanyAuthVo.class));
        } else {
            companyAuthBo =  companyService.authCompany(name);
            if(companyAuthBo != null){
                return ResponseDTO.succData(BeanUtil.copy(companyAuthBo,CompanyAuthVo.class));
            }
        }

        return ResponseDTO.succData(null);
    }

    @OperateLog(description = "企业认证")
    @GetMapping("/auth/update")
    public ResponseDTO<Boolean> updateCompanyAuthStatus(@RequestParam Long companyId){
        return ResponseDTO.succData(companyService.updateCompanyAuthStatus(companyId));
    }

    @GetMapping("/change")
    public ResponseDTO<Boolean> changeCompany(@RequestParam Long companyId,@RequestParam String name){
        return ResponseDTO.succData(companyService.changeCompany(companyId,name));
    }
}